package com.iplant.wms.serviceImpl.utils;

import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.CalendarTool;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.wms.service.basicenum.wms.WMSStockAlarmStatus;
import com.iplant.wms.service.po.hr.WMSStockAlarmHR;
import com.iplant.wms.service.po.hr.WMSStockAlarmItemHR;
import com.iplant.wms.service.po.mrp.MRPDelivery;
import com.iplant.wms.service.po.wms.WMSStock;
import com.iplant.wms.serviceImpl.dao.hr.WMSStockAlarmHRDAO;
import com.iplant.wms.serviceImpl.dao.hr.WMSStockAlarmItemHRDAO;
import com.iplant.wms.serviceImpl.dao.mrp.MRPDeliveryDAO;
import com.iplant.wms.serviceImpl.dao.wms.WMSStockRecordDAO;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class WMSAlarmUtils {

    private static WMSAlarmUtils Instance = null;

    public static WMSAlarmUtils getInstance() {
        if (Instance == null) {
            Instance = new WMSAlarmUtils();
        }
        return Instance;
    }

    public WMSAlarmUtils() {
    }

    /**
     * 检查库存是否满足需求
     * 要求每天干的活必须要要报工 扣减原料库存
     *
     * @param wLoginUser
     */
    public synchronized void WMS_StockAlarmCheckHR(BMSEmployee wLoginUser) {
        try {

            //step1 获取近两日配送需求
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Calendar wStartDate = CalendarTool.getDate();
            Calendar wEndDate = CalendarTool.getDate();
            wEndDate.add(Calendar.DATE, 2);

            //  查询现有物料配送需求
            List<MRPDelivery> wMRPDeliveryList = MRPDeliveryDAO.getInstance()
                    .MRP_SelectDeliveryListByDate(wLoginUser, wStartDate, wEndDate,
                            Pagination.getMaxSize(MRPDelivery.class), wErrorCode);
            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR MRP_SelectDeliveryListByDate Error: {}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }


            WMSStockAlarmHRDAO.getInstance().WMS_UpdateStockAlarmHRStatusCancel(wLoginUser, wErrorCode);
            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR WMS_UpdateStockAlarmHRStatusCancel Error: {}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }

            //step2  获取近两日库存预警列表  后面没有要创建

            List<WMSStockAlarmHR> wStockAlarmHRList = WMSStockAlarmHRDAO.getInstance().WMS_SelectStockAlarmHRList(wLoginUser,
                    wStartDate, wEndDate, Pagination.getMaxSize(WMSStockAlarmHR.class), wErrorCode);

            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR WMS_SelectStockAlarmHRList Error: {}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }


            if (wMRPDeliveryList == null || wMRPDeliveryList.size() == 0) {
                WMSStockAlarmHRDAO.getInstance().DeletePOList(wLoginUser, wStockAlarmHRList, wErrorCode);
                return;
            }
            wMRPDeliveryList.sort(Comparator.comparing(o -> o.DemandDate));

            List<Integer> wMaterialIDList = wMRPDeliveryList.stream().map(p -> p.MaterialID).distinct().collect(Collectors.toList());
            //step3 检查近两日需求数与当前剩余库存大小

            List<WMSStock> wStockList = WMSStockRecordDAO.getInstance().WMS_QueryStockCountList(wLoginUser,
                    wMRPDeliveryList.get(0).FactoryID, wMaterialIDList, Pagination.getNewMaxSize(), wErrorCode);
            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR WMS_QueryStockCountList Error:{}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                return;
            }

            Map<Integer, WMSStock> wStockMap = wStockList.stream().collect(Collectors.toMap(p -> p.MaterialID, p -> p, (o1, o2) -> o1));


            double wNeedNumber = 0;
            WMSStockAlarmHR wWMSStockAlarmHR;
            WMSStockAlarmItemHR wWMSStockAlarmItemHR;
            List<WMSStockAlarmItemHR> wWMSStockAlarmItemHRList=new ArrayList<>();
            List<Integer> wWMSStockAlarmHRIDList=new ArrayList<>();

            double wNeedNumberTemp;
            for (MRPDelivery wDelivery : wMRPDeliveryList) {

                wNeedNumber = wDelivery.PlanFQTY - wDelivery.FQTYUsed;
                if (wNeedNumber>0&& wStockMap.containsKey(wDelivery.MaterialID)) {

                    wNeedNumberTemp=wStockMap.get(wDelivery.MaterialID).MaterialNum - wStockMap.get(wDelivery.MaterialID).FreezeNum;

                    if(wNeedNumberTemp>0){
                        if(wNeedNumber>wNeedNumberTemp){
                            wStockMap.get(wDelivery.MaterialID).MaterialNum=wStockMap.get(wDelivery.MaterialID).FreezeNum;
                            wNeedNumber-=wNeedNumberTemp;
                        }else{
                            wStockMap.get(wDelivery.MaterialID).MaterialNum-=wNeedNumber;
                            wNeedNumber=0;
                        }
                    }
                }

                wWMSStockAlarmHR = this.GetStockAlarmHR(wStockAlarmHRList, wDelivery);

                //step4  如果有缺失
                if (wNeedNumber > 0) {
                    //step4.1 检查是否已有库存预警单据 没有需要生成 (主单、子单)
                    if (wWMSStockAlarmHR == null || wWMSStockAlarmHR.ID <= 0) {
                        wWMSStockAlarmHR = new WMSStockAlarmHR();

                        wWMSStockAlarmHR.FactoryID = wDelivery.FactoryID;
                        wWMSStockAlarmHR.FactoryCode = wDelivery.FactoryCode;
                        wWMSStockAlarmHR.FactoryName = wDelivery.FactoryName;
                        wWMSStockAlarmHR.OrderID = wDelivery.OrderID;
                        wWMSStockAlarmHR.OrderNo = wDelivery.OrderNo;
                        wWMSStockAlarmHR.StoreID = 0;
                        wWMSStockAlarmHR.StoreCode = "";
                        wWMSStockAlarmHR.StoreName = "";
                        wWMSStockAlarmHR.AlarmDate = wDelivery.DemandDate;
                        wWMSStockAlarmHR.Status=WMSStockAlarmStatus.Alarm.getValue();

                        WMSStockAlarmHRDAO.getInstance().UpdatePo(wLoginUser, wWMSStockAlarmHR, wErrorCode);

                        if (wErrorCode.Result != 0) {
                            log.info("WMS_StockAlarmCheckHR WMSStockAlarmHRDAO Update Error:{}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
                            continue;
                        }
                    }

                    if (wWMSStockAlarmHR.AlarmItemList == null)
                        wWMSStockAlarmHR.AlarmItemList = new ArrayList<>();

                    wWMSStockAlarmItemHR = this.GetStockAlarmItemHR(wWMSStockAlarmHR.AlarmItemList, wDelivery);
                    if (wWMSStockAlarmItemHR == null || wWMSStockAlarmItemHR.ID <= 0) {
                        wWMSStockAlarmItemHR=new WMSStockAlarmItemHR(wWMSStockAlarmHR,wDelivery.PlanFQTY);

                        wWMSStockAlarmItemHR.MaterialID = wDelivery.MaterialID;
                        wWMSStockAlarmItemHR.MaterialCode = wDelivery.MaterialCode;
                        wWMSStockAlarmItemHR.MaterialName = wDelivery.MaterialName;
                        wWMSStockAlarmItemHR.MaterialFullGroup = wDelivery.MaterialFullGroup;
                        wWMSStockAlarmItemHR.MaterialGroupID = wDelivery.MaterialGroupID;
                        wWMSStockAlarmItemHR.MaterialGroupCode = wDelivery.MaterialGroupCode;
                        wWMSStockAlarmItemHR.MaterialGroupName = wDelivery.MaterialGroupName;
                        wWMSStockAlarmItemHR.UnitID=wDelivery.UnitID;
                        wWMSStockAlarmItemHR.UnitText=wDelivery.UnitText;
                        wWMSStockAlarmItemHR.UnitCode=wDelivery.UnitCode;

                    }
                    //step4.2 已有库存预警单据需要调整缺失数量  与预警状态
                    wWMSStockAlarmItemHR.ShortFQTY=wNeedNumber;
                    wWMSStockAlarmItemHR.Status= WMSStockAlarmStatus.Alarm.getValue();

                    wWMSStockAlarmItemHRList.add(wWMSStockAlarmItemHR);
                    wWMSStockAlarmHRIDList.add(wWMSStockAlarmItemHR.StockAlarmID);

                } else {
                    //step5  如果无缺失
                    //step5.1 检查是否已有库存预警单据 没有就return
                    if (wWMSStockAlarmHR == null || wWMSStockAlarmHR.ID <= 0) {
                        continue;
                    }
                    if (wWMSStockAlarmHR.AlarmItemList == null)
                        wWMSStockAlarmHR.AlarmItemList = new ArrayList<>();

                    wWMSStockAlarmItemHR = this.GetStockAlarmItemHR(wWMSStockAlarmHR.AlarmItemList, wDelivery);
                    if(wWMSStockAlarmItemHR==null||wWMSStockAlarmItemHR.ID<=0)
                        continue;

                    //step5.2 已有库存预警单据需要调整缺失数量  与预警状态
                    wWMSStockAlarmItemHR.ShortFQTY=0;
                    wWMSStockAlarmItemHR.Status=WMSStockAlarmStatus.Close.getValue();
                    wWMSStockAlarmItemHRList.add(wWMSStockAlarmItemHR);
                    wWMSStockAlarmHRIDList.add(wWMSStockAlarmItemHR.StockAlarmID);
                }
            }

            WMSStockAlarmItemHRDAO.getInstance().UpdatePoList(wLoginUser, wWMSStockAlarmItemHRList, wErrorCode);
            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR WMSStockAlarmItemHRDAO UpdatePoList Error:{}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
            }
            WMSStockAlarmHRDAO.getInstance().WMS_UpdateStockAlarmHRStatus(wLoginUser, wWMSStockAlarmHRIDList, wErrorCode);
            if (wErrorCode.Result != 0) {
                log.info("WMS_StockAlarmCheckHR WMSStockAlarmHRDAO WMS_UpdateStockAlarmHRStatus Error:{}", ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
            }

        } catch (Exception ex) {
            log.error("WMS_StockAlarmCheckHR", ex);
        }

    }

    private WMSStockAlarmHR GetStockAlarmHR(List<WMSStockAlarmHR> wStockAlarmHRList, MRPDelivery wDelivery) {
        WMSStockAlarmHR wWMSStockAlarmHR = null;
        for (WMSStockAlarmHR wmsStockAlarmHR : wStockAlarmHRList) {
            if (CalendarTool.CompareDate(wmsStockAlarmHR.AlarmDate, wDelivery.DemandDate) != 0)
                continue;

            if (wmsStockAlarmHR.OrderID != wDelivery.OrderID)
                continue;

            if (wmsStockAlarmHR.FactoryID != wDelivery.FactoryID)
                continue;

            wWMSStockAlarmHR = wmsStockAlarmHR;
        }
        return wWMSStockAlarmHR;
    }

    private WMSStockAlarmItemHR GetStockAlarmItemHR(List<WMSStockAlarmItemHR> wStockAlarmHRList, MRPDelivery wDelivery) {
        WMSStockAlarmItemHR wWMSStockAlarmItemHR = null;
        for (WMSStockAlarmItemHR wItem : wStockAlarmHRList) {
            if (CalendarTool.CompareDate(wItem.AlarmDate, wDelivery.DemandDate) != 0)
                continue;

            if (wItem.OrderID != wDelivery.OrderID)
                continue;

            if (wItem.FactoryID != wDelivery.FactoryID)
                continue;

            if (wItem.MaterialID != wDelivery.MaterialID)
                continue;

            wWMSStockAlarmItemHR = wItem;
        }
        return wWMSStockAlarmItemHR;
    }

}
